#include "bsonclientpool.h"
#include "bsondoc.h"

BsonClientPool::BsonClientPool(const string& uri)
{
    m_clientpool = NULL;
    m_uri = NULL;

    static bool m_init = false;
    if ( !m_init )
    {
        mongoc_init();
        m_init = true;
    }
    else
        return;

    bson_error_t error;
    m_uri = mongoc_uri_new_with_error(uri.c_str(), &error);
    if ( !m_uri )
        return;

    m_clientpool = mongoc_client_pool_new(m_uri);
    mongoc_client_pool_set_error_api(m_clientpool, MONGOC_ERROR_API_VERSION_2);
}

mongoc_client_t* BsonClientPool::get()
{
    if ( m_clientpool == NULL )
        return NULL;
    return mongoc_client_pool_pop(m_clientpool);
}

void BsonClientPool::push(mongoc_client_t* pclient)
{
    if ( pclient == NULL || m_clientpool == NULL)
        return;
    mongoc_client_pool_push(m_clientpool,pclient);
}

BsonClientPool::~BsonClientPool()
{
    if ( m_clientpool != NULL )
    {
        mongoc_client_pool_destroy(m_clientpool);
        m_clientpool = NULL;
    }
    if ( m_uri != NULL )
    {
        mongoc_uri_destroy(m_uri);
        m_uri = NULL;
    }
}

void BsonClientPool::release()
{
    static bool cleaned = false;
    if ( !cleaned )
    {
        mongoc_cleanup();
        cleaned = true;
    }
}

bool ScopedBsonClient::insertOne( const string& db, const string& coll,bson_t* pinsert)
{
    if ( pinsert == NULL )
        return false;

    if ( m_client == NULL )
    {
        m_client = m_pool.get();
        if ( m_client == NULL )
            return false;
    }

    mongoc_collection_t *collection = 
        mongoc_client_get_collection (m_client, db.c_str(), coll.c_str() );

    if ( collection == NULL )
        return false;

    bson_error_t error;
    bool bret = mongoc_collection_insert_one(collection, pinsert, NULL, NULL, &error);
    mongoc_collection_destroy (collection);
    return bret;
}

string ScopedBsonClient::find(const string& db, const string& coll, bson_t* pquery)
{
    string strret;
    if ( pquery == NULL )
    {
        return strret;
    }

    if ( m_client == NULL )
    {
        m_client = m_pool.get();
        if ( m_client == NULL )
            return strret;
    }

    mongoc_collection_t *collection = 
        mongoc_client_get_collection (m_client, db.c_str(), coll.c_str() );

    if ( collection == NULL )
        return strret;

    mongoc_cursor_t *cursor = NULL;
    cursor = mongoc_collection_find_with_opts(collection, pquery, NULL, NULL);
    strret = BsonDoc::toJson(cursor);
    mongoc_cursor_destroy(cursor);
    mongoc_collection_destroy(collection);

    return strret;
}

bool ScopedBsonClient::updateOne(const string& db, const string& coll,bson_t* pquery, bson_t* pset)
{
    if ( pquery == NULL || pset == NULL)
        return false;

    if ( m_client == NULL )
    {
        m_client = m_pool.get();
        if ( m_client == NULL )
            return false;
    }

    mongoc_collection_t *collection = 
        mongoc_client_get_collection (m_client, db.c_str(), coll.c_str() );

    if ( collection == NULL )
        return false;

    bson_error_t error;
    bool bret = mongoc_collection_update_one(
          collection, pquery, pset, NULL, NULL, &error);
    
    mongoc_collection_destroy(collection);
    return bret;
}

bool ScopedBsonClient::deleteOne(const string& db, const string& coll,bson_t* pdel)
{
    if ( pdel == NULL )
        return false;

    if ( m_client == NULL )
    {
        m_client = m_pool.get();
        if ( m_client == NULL )
            return false;
    }

    mongoc_collection_t *collection = 
        mongoc_client_get_collection(m_client, db.c_str(), coll.c_str() );

    if ( collection == NULL )
        return false;

    bson_error_t error;
    bool bret = mongoc_collection_delete_one(collection, pdel, NULL, NULL, &error);
    mongoc_collection_destroy(collection);

    return bret;
}





